
package com.viweb.storemanager.core;

import java.awt.Image;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import javax.swing.filechooser.FileSystemView;
import sun.awt.shell.ShellFolder;

public class FileUtil {

    // Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) {
        byte[] bytes = null;
        try {
            InputStream is = new FileInputStream(file);

            // Get the size of the file
            long length = file.length();

            // You cannot create an array using a long type.
            // It needs to be an int type.
            // Before converting to an int type, check
            // to ensure that file is not larger than Integer.MAX_VALUE.
            if (length > Integer.MAX_VALUE) {
                // File is too large
            }

            // Create the byte array to hold the data
            bytes = new byte[(int) length];

            // Read in the bytes
            int offset = 0;
            int numRead = 0;
            while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
                offset += numRead;
            }

            // Ensure all the bytes have been read in
            if (offset < bytes.length) {
                throw new IOException("Could not completely read file " + file.getName());
            }

            // Close the input stream and return bytes
            is.close();
        } catch (Exception ex) {
        }
        return bytes;
    }

    public byte[] loadFromURL(URL url) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        InputStream is = url.openStream();
        byte[] buffer = new byte[8000];
        int r = is.read(buffer);

        while (r >= 0) {
            if (r == 0) {
                continue;
            }

            baos.write(buffer, 0, r);
        }
        is.close();

        return baos.toByteArray();
    }

    /**
     * This method is used to get the size of file
     * @param file: the file object is used
     * return file size in Megabyte
     */
    public static long getFileSizeInMegabyte(File file) {
        // Get the size of the file
        long length = file.length();

        return (length / (1024 * 1024));
    }

    /**
     * Get the system icon file which is define by the system
     * @param f the file object
     * return an icon
     */
    public static Icon getSystemIcon(File f) {
        if (f != null) {
            Class fsv = FileSystemView.class;
            try {
                Method m = fsv.getDeclaredMethod("getShellFolder", new Class[]{File.class});
                m.setAccessible(true);
                ShellFolder sf = (ShellFolder) m.invoke(FileSystemView.getFileSystemView(), f);
                Image img = sf.getIcon(true);
                if (img != null) {
                    return new ImageIcon(img, sf.getFolderType());
                } else {
                    return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * This method is used to get icon file which is define through each os
     * @param extension the file extension which means the extra after the dot '.'
     * in file name
     * It used the method getSystemIcon to get Icon file
     */
    public static Icon getIcone(String extension) {
        File file;
        String cheminIcone = "";
        if (((System.getProperties().get("os.name").toString()).startsWith("Mac"))) {
            cheminIcone = System.getProperties().getProperty("file.separator");
        } else if (((System.getProperties().get("os.name").toString()).startsWith("Linux"))) {
            cheminIcone = "/" + "tmp" + "/BoooDrive-" + System.getProperty("user.name") + "/";
        } else {
            cheminIcone = System.getenv("TEMP") + System.getProperties().getProperty("file.separator");
        }
        File repIcone = new File(cheminIcone);
        if (!repIcone.exists()) {
            repIcone.mkdirs();
        }
        try {
            if (extension.equals("FOLDER")) {
                file = new File(cheminIcone + "icon");
                file.mkdir();
            } else {
                file = new File(cheminIcone + "icon." + extension.toLowerCase());
                file.createNewFile();
            }

            Icon icone = getSystemIcon(file);

            file.delete();
            return icone;
        } catch (IOException e) {
        }
        return null;
    }

    /**
     * This method is used to get the extra name after dot in file name
     * @param name the name of file which means file name or file path include name
     * return file extension such as: gif, jpg, ..
     */
    public static String getExtension(String name) {
        if (name.lastIndexOf(".") != -1) {
            String extensionPossible = name.substring(name.lastIndexOf(".") + 1, name.length());
            if (extensionPossible.length() > 6) {
                return "";
            } else {
                return extensionPossible;
            }
        } else {
            return "";
        }
    }

    /**
     * This method is used to delete a file
     * @filePath the path of file is need delete
     * It's check file first and delete if file is good
     */
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.isFile() && file.canWrite()) {
            file.delete();
        }
    }

    /**
     * This method is used to copy a file to another location
     * @param srcFile include the path of source file
     * @param dtFile the destination path include new file name
     */
    public static void copyFile(String srcFile, String dtFile) {
        try {
            File f1 = new File(srcFile);
            File f2 = new File(dtFile);
            InputStream in = new FileInputStream(f1);

            //For Append the file.
            //OutputStream out = new FileOutputStream(f2,true);

            //For Overwrite the file.
            OutputStream out = new FileOutputStream(f2);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
        } catch (FileNotFoundException ex) {
            System.out.println(ex.getMessage() + " in the specified directory.");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * This method is used to copy a file to another location
     * @param srcFile include the path of source file
     * @param dtFile the destination path include new file name
     */
    public static void copyFile(File srcFile, String dtFile) {
        try {
            File f2 = new File(dtFile);
            InputStream in = new FileInputStream(srcFile);

            //For Append the file.
            //OutputStream out = new FileOutputStream(f2,true);

            //For Overwrite the file.
            OutputStream out = new FileOutputStream(f2);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
        } catch (FileNotFoundException ex) {
            System.out.println(ex.getMessage() + " in the specified directory.");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * This method is used to convert a path with the mark "\\" to "/"
     * It's used to valid the path to every system
     */
    public static String convertFilePath(String path) {
        if (!path.isEmpty()) {
            path = path.replace("\\", "/");
            if (path.indexOf("\\") == -1) {
                return path;
            }
        } else {
            return "";
        }
        return path;
    }

    /**
     *  This method used to download file from URL
     *  @param srcFile the URL path
     *  @param dtFile the destination path include new file name will be save
     */
    public static boolean getFileFromUrl(String srcFile, String dtFile) {
        boolean result = true;
        if (!srcFile.isEmpty()) {
            try {
                URL url = new URL(srcFile);
                URLConnection urlC = url.openConnection();
                urlC.getContentLength();
                InputStream is = url.openStream();
                System.out.flush();
                FileOutputStream fos = null;
                File f = new File(dtFile);
                fos = new FileOutputStream(f);
                int oneChar, count = 0;
                while ((oneChar = is.read()) != -1) {
                    fos.write(oneChar);
                    count++;
                }
                is.close();
                fos.close();
            } catch (MalformedURLException e) {
                result = false;
                System.err.println(e.toString());
            } catch (IOException ie) {
                result = false;
                System.err.println(ie.toString());
            } catch (Exception ex) {
                result = false;
                System.err.println(ex.toString());
            }
        }
        return result;
    }

    /** 
     * Deletes all files and subdirectories under dir.
     * returns true if all deletions were successful.
     * If a deletion fails, the method stops attempting to delete and returns false.
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }

        // The directory is now empty so delete it
        return dir.delete();
    }

    /** 
     * Copies all file and directory from srcFile to under dtFile path.
     * @param srcFile source path
     * @param dtFile directory which stores file-copied
     * returns true if copied file were successful.
     */
    public static boolean copyFile2File(String srcFile, String dtFile) {
        boolean success = true;
        File f = new File(srcFile);
        if (f.exists() && f.isDirectory()) {
            File dir = new File(dtFile + "\\" + f.getName());
            dir.mkdir();
            return success;
        }
        try {
            // Create channel on the source
            FileChannel srcChannel = new FileInputStream(srcFile).getChannel();

            // Create channel on the destination
            FileChannel dstChannel = new FileOutputStream(dtFile + "\\" + f.getName()).getChannel();

            // Copy file contents from source to destination
            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());

            // Close the channels
            srcChannel.close();
            dstChannel.close();
        } catch (IOException e) {
            success = false;
        }
        return success;
    }

    /**
     *
     * @author Nguyễn Anh Minh
     * Process all files and directories under dir
     * This method is a recursive procedure which is used to copy all files and     
     * sub folders from a source folder to destination directory
     * @param srcFile the source file
     * @param dtFile the destination file which is had the same content of source 
     * file
     */
    public static boolean copyAllDirsAndFiles(File srcFile, String dtFile) {
        boolean success = true;
        if (!srcFile.exists()) {
            return false;
        }
        if (srcFile.isDirectory()) {
            String[] children = srcFile.list();
            for (int i = 0; i < children.length; i++) {
                if (copyFile2File(srcFile.getPath() + "\\" + children[i], dtFile)) {
                    success = copyAllDirsAndFiles(new File(srcFile, children[i]), (dtFile + "\\" + children[i]));
                }
            }
        }
        return success;
    }

    public static String getFileName(String filePath) {
        String fileName = filePath.substring(
                filePath.lastIndexOf("\\") + 1,
                filePath.length());
        return fileName;
    }

    public static String createTempFile(byte[] b, String fileName) {
        String filePath = null;

        if (fileName == null) {
            fileName = "tmp_photo.jpg";
        }

        if (b == null) {
            return filePath;
        }

        int dotPos = fileName.lastIndexOf(".");
        /*
         * This is the name that be saved on the temporary folder. Now we let it name
         * default is photo because the user can select a photo with the filename
         * less than 3 charactor, it will appear error. It's name is only use to
         * save in the temp file not for the system database so we don't care it now.
         */
        String extension = fileName.substring(dotPos);
        try {
            File temporaryFile;
            temporaryFile = File.createTempFile("Photo", extension);
            temporaryFile.deleteOnExit();

            FileOutputStream out = new FileOutputStream(temporaryFile);
            out.write(b);
            out.close();

            filePath = temporaryFile.getAbsolutePath();
        } catch (IOException ex) {
            return null;
        }

        return filePath;
    }
}
